﻿using Qing.Lang;
using Qing.Std;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Qing.Proto {
    class CreateHashMapObj : Native {
        public override string Name { get; set; } = "创建哈希表";
        public override string Desc { get; set; } = "参数1-数组，返回哈希表对象；创建哈希表";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
            HashMapObj dict = new HashMapObj();
            if (args.Count > 0 && args[0].Tp == TP.Arr) {
                foreach(var item in args[0].List!) {
                    if(item.Tp != TP.Arr || item.List!.Count < 2) {
                        return Expr.Err("创建哈希表的初始化参数有误");
                    }
                    dict.Set(item.List[0], item.List[1]);
                }

            }

            return new Expr(TP.Obj, dict);
        }
    }


    public class HashMapObj : Obj {

        public HashMapObj() {
            Raw = new Dictionary<string, (Expr,Expr)>();

            Map["@设"] = new Expr(new DictSet());
            Map["@取"] = new Expr(new DictGet());
            Map["@删除"] = new Expr(new DictRemove());
            Map["@包含"] = new Expr(new DictContainsKey());
            Map["@数量"] = new Expr(new DictCount());
            Map["@转数组"] = new Expr(new Dict2Arr());
        }


        public static string Expr2Key(Expr key) {
            string k = key.Tp.ToString();
            switch (key.Tp) {
                case TP.None:
                case TP.Bool:
                case TP.Int:
                case TP.Float:
                case TP.Bin:
                case TP.Arr:
                    k += key.ToStr();
                    break;

                case TP.Str:
                    k += key.Str();
                    break;

                default:
                    k += key.Val.GetHashCode();
                    break;
            }

            return k;
        }

        public int Set(Expr key, Expr val) {
            string k = Expr2Key(key);

            Dictionary<string, (Expr, Expr)> dict = (Dictionary<string, (Expr, Expr)>)Raw;
            bool haskey = dict.ContainsKey(k);
            dict[k] = (key.Dup(), val);
            if (haskey) {
                return 0;
            } else {
                return 1;
            }
        }

        public Expr GetOrDefault(Expr key, Expr? def = null) {
            string k = Expr2Key(key);

            Dictionary<string, (Expr, Expr)> dict = (Dictionary<string, (Expr, Expr)>)Raw;
            if (dict.ContainsKey(k)) {
                return dict[k].Item2;
            } else {
                if(def == null) {
                    return Expr.NoneExpr;
                }
                return def;
            }

        }

        public bool ContainsKey(Expr key) {
            string k = Expr2Key(key);

            Dictionary<string, (Expr, Expr)> dict = (Dictionary<string, (Expr, Expr)>)Raw;
            return dict.ContainsKey(k);
        }

        class DictGet : Native {
            public override string Name { get; set; } = "取";
            public override string Desc { get; set; } = "参数1-任意，可选参数2-任意，返回任意类型；参数1作为键，获取对应的值，键不存在是返回空或参数2的值";
            public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
                HashMapObj map = (HashMapObj)obj!;

                if(args.Count > 1) {
                    return map.GetOrDefault(args[0], args[1]);
                }else if (args.Count > 0) {
                    return map.GetOrDefault(args[0]);
                }

                return Expr.Err("哈希表@取 函数需要至少1个参数");
            }
        }

        class DictSet : Native {
            public override string Name { get; set; } = "设";
            public override string Desc { get; set; } = "参数1-任意，参数2-任意，返回整数；参数1作为键，设置为参数2对应的值，插入返回1，更新返回0";
            public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {
                HashMapObj map = (HashMapObj)obj!;
                if(args.Count < 2) {
                    return Expr.Err("哈希表@设 函数需要至少2个参数");
                }

                return new Expr(TP.Int, map.Set(args[0], args[1]));

            }
        }

        class DictRemove : Native {
            public override string Name { get; set; } = "删除";
            public override string Desc { get; set; } = "参数1-任意，返回逻辑；参数1作为键，从哈希表中删除键值对";
            public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {

                if (args.Count < 1) {
                    return Expr.Err("哈希表@删除 函数需要至少1个参数");
                }

                Dictionary<string, (Expr, Expr)> dict = (Dictionary<string, (Expr, Expr)>)obj!.Raw;
                string k = HashMapObj.Expr2Key(args[0]);
                if (dict.ContainsKey(k)) {
                    dict.Remove(k);
                    return new Expr(TP.Int, 1);
                } else {
                    return new Expr(TP.Int, 0);
                }

            }
        }

        class DictContainsKey : Native {
            public override string Name { get; set; } = "包含";
            public override string Desc { get; set; } = "参数1-任意，返回逻辑；参数1作为键，判断哈希表是否包含键";
            public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {

                if (args.Count < 1) {
                    return Expr.Err("哈希表@包含 函数需要至少1个参数");
                }

                Dictionary<string, (Expr, Expr)> dict = (Dictionary<string, (Expr, Expr)>)obj!.Raw;
                return new Expr(TP.Bool, dict.ContainsKey(HashMapObj.Expr2Key(args[0])));

            }
        }

        class DictCount : Native {
            public override string Name { get; set; } = "数量";
            public override string Desc { get; set; } = "无参，返回整数；返回哈希表中键值对数量";
            public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {

                Dictionary<string, (Expr, Expr)> dict = (Dictionary<string, (Expr, Expr)>)obj!.Raw;
                return new Expr(TP.Int, dict.Count);

            }
        }

        class Dict2Arr : Native {
            public override string Name { get; set; } = "转数组";
            public override string Desc { get; set; } = "无参，返回数组；将哈希表转为数组";
            public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj = null, List<Expr>? namedArgs = null) {

                Dictionary<string, (Expr, Expr)> dict = (Dictionary<string, (Expr, Expr)>)obj!.Raw;

                List<Expr> list = new List<Expr>();
                foreach(var item in dict.Values) {
                    List<Expr> pair = new List<Expr>();
                    pair.Add(item.Item1);
                    pair.Add(item.Item2);
                    list.Add(new Expr(TP.Arr, 0, pair));
                }

                return new Expr(TP.Arr, 0, list);
            }
        }


    }
}
